import cx_Oracle
import logging
import time
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime
from config_loader import ConfigLoader
from db_manager import DatabaseManager
from status_manager import StatusManager
from alert_manager import AlertManager
import os
from config_loader import ConfigLoader

# 获取配置文件路径
config_path = os.environ.get('DAYCHECK_CONFIG', 'config.yaml')
config = ConfigLoader(config_path)

class OracleChecker:
    def __init__(self):
        # 加载配置
        self.config = ConfigLoader(config_path)
        
        # 初始化数据库管理器
        db_config = self.config.get_database_config()
        self.db_manager = DatabaseManager(
            db_path=db_config['status_db'],
            min_connections=db_config['min_connections'],
            max_connections=db_config['max_connections'],
            timeout=db_config['timeout']
        )
        
        # 初始化状态管理器
        self.status_manager = StatusManager(self.db_manager)
        
        # 初始化告警管理器
        wx_config = self.config.get_wx_alert_config()
        self.alert_manager = AlertManager(
            webhook=wx_config['webhook'],
            retry=wx_config['retry'],
            timeout=wx_config['timeout']
        )
        
        # 初始化日志配置
        log_config = self.config.get_logging_config()
        logging.basicConfig(
            level=getattr(logging, log_config['level']),
            format=log_config['format'],
            handlers=[
                logging.FileHandler(log_config['file']),
                logging.StreamHandler()
            ]
        )
        
        # 加载Oracle实例配置
        self.groups = self.config.parse_oracle_config('/home/ai/dev/daycheck/dbconfig')

    def handle_instance_status(self, instance, result):
        """处理实例状态更新和告警"""
        details = str(result)
        current_status = 'Normal' if 'OPEN' in result else 'Failed'
        max_retries = 3
        retry_count = 0

        while retry_count < max_retries:
            try:
                if current_status == 'Failed':
                    # 处理失败状态
                    logging.error(f"{instance['name']} 状态异常: {details}")
                    self.alert_manager.send_instance_alert(
                        instance_name=instance['name'],
                        host=f"{instance['host']}/{instance['service']}",
                        status=details,
                        is_normal=False
                    )
                    self.status_manager.update_instance_status(
                        db_name=instance['name'],
                        status='Failed',
                        details=result
                    )
                    return False, details
                else:
                    # 处理正常状态
                    logging.info(f"{instance['name']} 连接 {instance['host']}/{instance['service']} 状态: {current_status}")
                    self.status_manager.update_instance_status(
                        db_name=instance['name'],
                        status=current_status,
                        details=f"状态: {result}"
                    )
                    return True, current_status
            except Exception as e:
                retry_count += 1
                if retry_count < max_retries:
                    logging.warning(f"更新状态失败，正在进行第{retry_count}次重试: {str(e)}")
                    time.sleep(1)  # 重试前等待1秒
                else:
                    logging.error(f"更新状态失败，已达到最大重试次数: {str(e)}")
                    raise

    def check_instance(self, instance):
        """检查单个Oracle实例状态"""
        try:
            dsn = f"{instance['host']}/{instance['service']}"
            with cx_Oracle.connect(
                user=instance['user'],
                password=instance['password'],
                dsn=dsn
            ) as conn:
                with conn.cursor() as cursor:
                    cursor.execute("SELECT status FROM v$instance")
                    status = cursor.fetchone()[0]
                    return self.handle_instance_status(instance, status)

        except Exception as e:
            #error_msg = f"{instance['name']} 连接 {instance['host']}/{instance['service']} 失败: {str(e)}"
            return self.handle_instance_status(instance, f"{str(e)}")

    def run_checks(self):
        """运行所有实例检查"""
        with ThreadPoolExecutor() as executor:
            results = {}
            all_normal = True
            # 按组存储实例状态
            group_instances_status = {}

            for group, instances in self.groups.items():
                group_results = list(executor.map(self.check_instance, instances))
                results[group] = group_results
                group_instances_status[group] = []
                
                for (success, status), instance in zip(group_results, instances):
                    if not success:
                        all_normal = False
                    # 创建包含实例详细信息的字典
                    instance_status = {
                        'name': instance['name'],
                        'host': instance['host'],
                        'service': instance['service'],
                        'status': status,
                        'is_normal': success,
                        'group': group
                    }
                    group_instances_status[group].append(instance_status)
            
            # 检查是否为当天首次运行
            is_first_run_today = not self.status_manager.check_daily_notification_sent()
            
            # 如果是当天首次运行，按组分别发送全量状态报告
            if is_first_run_today:
                logging.info("当天首次运行检查，按组分别发送全量状态报告")
                
                # 遍历每个组，分别发送报告
                for group, instances_status in group_instances_status.items():
                    if instances_status:  # 确保组内有实例
                        logging.info(f"发送 {group} 组的状态报告")
                        self.alert_manager.send_full_status_report(instances_status)
                
                # 记录已发送每日通知
                self.status_manager.record_daily_notification()
                logging.info("全量状态报告已发送")
            
            return results

    def generate_report(self, results):
        """生成检查报告"""
        log_file = f"/home/ai/dev/daycheck/logs/check_{datetime.now().strftime('%Y%m%d%H%M%S')}.log"
        try:
            with open(log_file, 'a') as f:
                f.write(f'=== 检查开始 {datetime.now()} ===\n')
                for group, group_results in results.items():
                    f.write(f'\n=== {group} 检查结果 ===\n')
                    for (success, status), instance in zip(group_results, self.groups[group]):
                        result = '成功' if success else '失败'
                        f.write(f'{instance["name"]}@{instance["host"]}: {result} - {status}\n')
                f.write(f'\n=== 检查结束 {datetime.now()} ===\n')
        except Exception as e:
            logging.error(f"生成报告失败: {str(e)}")

if __name__ == '__main__':
    checker = OracleChecker()
    try:
        results = checker.run_checks()
        checker.generate_report(results)
    finally:
        checker.db_manager.close_all()